/**
 * Timeless - resource.cpp
 */
 
#include "resource.h"

std::list<Thing *> Thing::activeThings;
std::list<Thing *> Thing::deadThings;

Thing::Thing() {
    activeThings.push_back(this);
    refCount = 0;
}   

Thing::~Thing() {
    deadThings.push_back(this);
}

void Thing::add() {
    ++refCount;
}

void Thing::remove() {
    --refCount;
    if( refCount <= 0 ) {
        activeThings.remove(this);
        deadThings.push_back(this);
    }
}

void Thing::garbageCollector() {
    std::list<Thing *>::iterator it;
    for( it = deadThings.begin(); it != deadThings.end(); it++ ) {
        delete (*it);
    }
    
    deadThings.clear();
}

void Thing::goingDown() {
    garbageCollector();
    std::list<Thing *>::iterator it;
    for( it = activeThings.begin(); it != activeThings.end(); it++ ) {
        Thing *o = (*it);
        ///@todo Logging.
        delete o;
    }
    activeThings.clear();
}

Preferences::Preferences() {
    settingMap.clear();
    defaultSettings();
}

Preferences::~Preferences() {
    destroySettings();
}

void Preferences::registerVar(std::string &name, Thinglike<NoForm> &var) {
    settingMap[name] = var;
}

void Preferences::parseFile(std::string filename) {
    std::ifstream in(filename.c_str());
    if( !in.is_open() )
        return;
    
    while( !in.eof() ) {
        char szBuf[1024];
        in.getline(szBuf, 1024);
        parseLine(szBuf);
    }
}

void Preferences::defaultSettings() {
}

void Preferences::destroySettings() {
}

void Preferences::set(std::string &name, std::string &value, int bias) {
    if( !settingMap[name])
        return;
        
    (*settingMap[name]) = value;
}

void Preferences::parseLine(std::string str) {
    int bias=0; std::string name, value;
    
    if( (str[0] == '+') || (str[0] == '-') ) {
        bias = ( (str[0] == '+') * 2) - 1;
        str = str.substr(1);
    }
    
    int eqPos = str.find('=');
    if( eqPos != -1 ) {
        name = str.substr(0, eqPos);
        value = str.substr(eqPos+1);
    } else {
        name = str;
        char szBuf[5];
        sprintf(szBuf, "%i", (bias + 1) / 2);
        value = szBuf;
    }
    
    set(name, value, bias);
}

GameKernel::GameKernel() {
    int width, height, bpp;
    int flags;
    
    if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) {
        // Um, how do I shot out?
    }
    
    width = 800;
    height = 600;
    bpp = 32;
    
    flags = SDL_OPENGL | SDL_FULLSCREEN;
}

GameKernel::~GameKernel() {
    SDL_Quit();
}

int GameKernel::exec() {
    while(activeTasks.size()) {
        std::list<Thinglike<Action> >::iterator it;
        for( it = activeTasks.begin(); it != activeTasks.end(); ) {
            Action *a = (*it);
            it++;
            if( !a->canKill )
                a->update();
            
        }
        
        for( it = activeTasks.begin(); it != activeTasks.end(); ) {
            Action *a = (*it);
            it++;
            if( a->canKill ) {
                a->stop();
                activeTasks.remove(a);
                a = 0;
            }
        }
        Thing::garbageCollector();
    }
    return 0;
}

bool GameKernel::addTask(Thinglike<Action> &a) {
    if( !a->start() )
        return false;
    
    std::list<Thinglike<Action> >::iterator it;
    for( it = activeTasks.begin(); it != activeTasks.end(); it++ ) {
        Thinglike<Action> comp;
        if( comp->priority > a->priority )
            break;
    }
    
    activeTasks.insert(it, a);
    return true;
}

void GameKernel::wakeTask(Thinglike<Action> &a) {
    if( std::find(sleepingTasks.begin(), sleepingTasks.end(), a ) != sleepingTasks.end() ) {
        a->onWake();
        sleepingTasks.remove(a);
        std::list<Thinglike<Action> >::iterator it;
        for( it = activeTasks.begin(); it != activeTasks.end(); it++ ) {
            Thinglike<Action> comp;
            if( comp->priority > a->priority )
                break;
        }
        activeTasks.insert(it, a);
    }
}

void GameKernel::sleepTask(Thinglike<Action> &a) {
    if( std::find(activeTasks.begin(), activeTasks.end(), a) != activeTasks.end() ) {
        a->onSleep();
        activeTasks.remove(a);
        sleepingTasks.push_back(a);
    }
}

void GameKernel::removeTask(Thinglike<Action> &a) {
    std::list<Thinglike<Action> >::iterator it;
    for( it = activeTasks.begin(); it != activeTasks.end(); it++ ) {
        (*it)->canKill = true;
    }
}

void GameApplication::Run( int argc, char *argv[] ) {
    new Preferences;
    new GameKernel;
    
    Preferences::get().parseFile("settings.conf");
    GameKernel::get().exec();
    
    delete GameKernel::getPointer();
    delete Preferences::getPointer();
}
